RPCGEN
Section: User Commands (1)
Updated: 11 March 1986
Index
Return to Main Contents
NAME
rpcgen - an RPC protocol compiler
SYNOPSIS
rpcgen -h [-o outfile] [inputfile]
rpcgen -c [-o outfile] [infile]
rpcgen infile
rpcgen [-s transport]* [-o outfile] [infile]
DESCRIPTION
rpcgen is a tool that generates
C
code to implement an
RPC
protocol. The input to rpcgen is a language with striking
similarity to
C
known as RPCL (Remote Procedure Call Language).
rpcgen
operates in four modes. The first mode is used to convert
RPCL definitions into
C
definitions for use as a header file.
The second mode compiles the XDR routines required to serialize the protocol
described by RPCL. The third mode compiles both, leaving the
header file in a file named infile with a
.h
extension and the XDR routines in infile with a
.c
extension. The fourth mode is used to compile an RPC server skeleton, so that
all you have to do is write local procedures that know nothing about RPC
in order to implement an RPC server.
The input may contain
C-style
comments and preprocessor directives. Comments are ignored, while the
directives are simply stuffed uninterpreted in the output header file.
You can customize some of your XDR routines by leaving those data
types undefined. For every data type that is undefined, rpcgen
will assume that there exists a routine with the name `xdr_' prepended
to the name of the undefined type.
OPTIONS
- -c
-
Compile XDR routines.
- -h
-
Compile
C
data-definitions (a header file)
- -o outfile
-
Specify the name of the output file. If none is specified, standard
output is used (-c, -h and -s modes only).
- -s transport
-
Compile a server, using the the given transport. The supported transports
are udp and tcp. This option may be invoked more than once
so as to compile a server that serves multiple transports.
USAGE
RPCL Syntax Summary
This summary of RPCL syntax, which is used for
rpcgen
input, is intended more for aiding
comprehension than as an exact statement of the language.
Primitive Data Types
-
[ unsigned ] char
[ unsigned ] short
[ unsigned ] int
[ unsigned ] long
unsigned
float
double
void
bool
Except for the added boolean data-type bool,
RPCL is identical to
C.
rpcgen converts bool declarations to int declarations in the
output header file (literally it is converted to a bool_t, which has been
#define'd to be an int). Also, void declarations
may appear only inside of
union
and
program
definitions. For those averse to typing the prefix
unsigned, the abbreviations u_char, u_short, u_int and
u_long are available.
Declarations
RPCL allows only three kinds of declarations:
declaration:
-
simple-declaration
pointer-declaration
vector-declaration
simple-declaration:
-
type-name object-ident
pointer-declaration:
-
type-name *object-ident
vector-declaration:
-
type-name object-ident[size]
(size can be either an integer or a symbolic constant)
RPCL declarations contain both limitations and extensions with
respect to
C.
The limitations are that you cannot declare
multidimensional arrays or pointers-to-pointers in-line (You
can still declare them though, using typedef). There
are two extensions:
-
Opaque data is declared as a vector as follows:
-
opaque object-ident [ size ]
In the protocol, this results in an object of size bytes. Note that
this is not the same as a declaration of size characters,
since XDR characters are 32-bits. Opaque declarations are compiled in the
output header file into character array declarations of size bytes.
Strings are special and are declared as a vector declaration:
-
string object-ident [ max-size ]
If max-size is unspecified, then there is essentially no limit to
the maximum length of the string. String declarations get compiled into
the following:
-
char *object-ident
Type Definitions
The only way to generate an XDR routine is to define a type. For
every type zetype you define, there is a corresponding
XDR routine named xdr_zetype.
There are six ways to define a type:
type-definition:
-
typedef
enumeration-def
structure-def
variable-length-array-def
discriminated-union-def
program-def
The first three are very similar to their
C
namesakes.
C
does not have a formal type mechanism to define variable-length arrays and
XDR unions are quite different from their
C
counterparts. Program definitions are not really type definitions,
but they are useful nonetheless.
You may not nest XDR definitions. For example, the following will
cause rpcgen to choke:
-
struct dontdoit {
struct ididit {
int oops;
} sorry;
enum ididitagain { OOPS, WHOOPS } iapologize;
};
Typedefs
An XDR typedef looks as follows:
typedef:
-
typedef declaration ;
The object-ident part of declaration is the name of the new type,
whereas the type-name part is the name of the type from which it is
derived.
Enumeration Types
The syntax is:
enumeration-def:
-
enum enum-ident {
-
enum-list
};
enum-list:
-
enum-symbol-ident [ = assignment ]
enum-symbol-ident [ = assignment ] , enum-list
(assignment may be either an integer or a symbolic constant)
If there is no explicit assignment, then the implicit assignment is the
value of the previous enumeration plus 1. If not explicitly assigned,
the first enumeration receives the value 0.
Structures
structure-def:
-
struct struct-ident {
-
declaration-list
};
declaration-list:
-
declaration ;
declaration ; declaration-list
Variable-Length Arrays
variable-length-array-def:
-
array array-ident {
-
unsigned length-identifer ;
vector-declaration ;
};
A variable length array definition looks much like a structure
definition. Here's an example:
-
array mp_int {
unsigned len;
short val[MAX_MP_LENGTH];
};
This is compiled into:
-
struct mp_int {
unsigned len;
short *val;
};
typedef struct mp_int mp_int;
Disriminated Unions
discriminated-union-def:
-
union union-ident switch ( discriminant-declaration ) {
-
case-list
[ default : declaration ; ]
};
case-list:
-
case case-ident : declaration ;
case case-ident : declaration ; case-list
discriminant-declaration:
-
declaration
The union definition looks like a cross between a C-union and a C-switch.
An example:
-
union net_object switch (net_kind kind) {
case MACHINE:
struct sockaddr_in sin;
case USER:
int uid;
default:
string whatisit;
};
Compiles into:
-
struct net_object {
net_kind kind;
union {
struct sockaddr_in sin;
int uid;
char *whatisit;
} net_object;
};
typedef struct net_object net_object;
Note that the name of the union component of the output struct is the
same as the name of the type itself.
Program Definitions
program-def:
-
program program-ident {
-
version-list
} = program-number ;
version-list:
-
version
version version-list
version:
-
version version-ident {
-
procedure-list
} = version-number ;
procedure-list:
-
procedure-declaration
procedure-declaration procedure-list
procedure-declaration:
-
type-name procedure-ident ( type-name ) = procedure-number ;
Program definitions look like nothing you've ever seen before, so we
turn to an example to explain them. Suppose you wanted to create server
that could get or set the date. It's declaration might look like this:
-
program DATE_PROG {
version DATE_VERS {
date DATE_GET(timezone) = 1;
void DATE_SET(date) = 2; /* Greenwich mean time */
} = 1;
} = 100;
In the header file, this compiles into the following:
-
#define DATE_PROG 100
#define DATE_VERS 1
#define DATE_GET 1
#define DATE_SET 2
These define's are intended for use by the client program to
reference the remote procedures.
If you are using rpcgen to compile your server, then there are
some important things for you to know. The server interfaces to
your local procedures by expecting a
C
function with the same name as that in the program definition, but in all
lower-case letters and followed by the version number. Here is the local
procedure that implements DATE_GET:
-
date * /* always returns a pointer to the results */
date_get_1(tz)
timezone *tz; /* always takes a a pointer to the arguments */
{
static date d; /* must be static! */
/*
* figure out the date
* and store it in d
*/
return(&d);
}
The name of the routine is the same as the #define'd name, but in all
lower case letters and followed by the version number. XDR will recursively
free the argument after getting the
results from your local procedure, so you should copy from the argument
any data that you will need between calls. However, XDR neither allocates
nor frees your results. You must take care of their storage yourself.
Make Inference Rules For Compiling XDR Headers
It is possible to set up suffix transformation rules in
make(1)
for compiling XDR routines and header files. The
convention is that RPCL protocol files have the extension
.x.
The make rules to do this are:
.SUFFIXES: .x
.x.c:
rpcgen -c $< -o $@
.x.h:
rpcgen -h $< -o $@
SEE ALSO
Remote Procedure Call: Programming Guide
and External Data Representation: Protocol Specification
in Networking on the Sun Workstation
BUGS
Name clashes can occur when using program definitions, since the apparent
scoping does not really apply. Most of these can be avoided by giving
unique names for programs, versions, procedures and types.
Index
- NAME
-
- SYNOPSIS
-
- DESCRIPTION
-
- OPTIONS
-
- USAGE
-
- RPCL Syntax Summary
-
- Primitive Data Types
-
- Declarations
-
- Type Definitions
-
- Typedefs
-
- Enumeration Types
-
- Structures
-
- Variable-Length Arrays
-
- Disriminated Unions
-
- Program Definitions
-
- Make Inference Rules For Compiling XDR Headers
-
- SEE ALSO
-
- BUGS
-
This document was created by
man2html,
using the manual pages.
Time: 22:49:32 GMT, December 11, 2024